# -*- coding: utf-8 -*-
import FPLib
import tornado.httpserver
import tornado.ioloop
import tornado.web
import tornado.gen

from tornado.concurrent import run_on_executor
from concurrent.futures import ThreadPoolExecutor

from torndsession.sessionhandler import SessionBaseHandler

from .ServerHandler import ServerHandler
from .FPAPIHandler import FPAPIHandler


class WebServer:

    def __init__(self):
        self.server = False
        self.port = 80
        self.Handler = []
        self.staticHandler = []
        self.ui_modules = {}
        self.template_path = ""
        self.app = False
        self.is_single = False
        self.__function_list = {}

    def route(self, r, handler, handlerClass=None, data=None):
        keys = "hd" + str(id(handler))
        if keys not in self.__function_list:
            if handlerClass:
                classlist = (ServerHandler, SessionBaseHandler, handlerClass)
            else:
                classlist = (ServerHandler, SessionBaseHandler)
            self.__function_list[keys] = type(
                keys,
                classlist,
                dict(handler=run_on_executor(handler))
            )
        self.Handler.append((
            r,
            self.__function_list[keys],
            dict(data=data)
        ))
        # print("self.Handler",self.Handler)

    def FPAPI(self, path="wwwroot", APIhandlerClass=None, PagehandlerClass=None, data=None, apiInit=None, pageInit=None):
        path = path.rstrip("/")
        self.wwwroot(path)
        self.page("/page/", path=path + "/page/", handlerClass=PagehandlerClass, data=data, init=apiInit)
        self.api("/api/", path=path + "/api/", handlerClass=APIhandlerClass, data=data, init=pageInit)
        self.template(path=path + "/templates/")

    def api(self, r="/api", path="api", handlerClass=None, data=None, init=None):
        r = r.rstrip("/") + "/(.*)"
        path = FPLib.FILE(path)

        api = FPAPIHandler()
        api.set(r, path, type="api", init=init)

        self.route(r, api.handler, handlerClass=handlerClass, data=data)

    def wwwroot(self, path="wwwroot", r="/"):
        self.static(r, path)
        if self.template_path == "":
            self.template()

    def page(self, r="/page/", path="page", handlerClass=None, data=None, init=None):
        r = r.rstrip("/") + "/(.*)"
        path = FPLib.FILE(path)

        page = FPAPIHandler()
        page.set(r, path, type="page", init=init)

        self.route(r, page.handler, handlerClass=handlerClass, data=data)

    def static(self, r="/", path="wwwroot"):
        if r[-1] == "/":
            r += "(.*)"
        path = FPLib.FILE(path)
        self.staticHandler.append((
            r,
            tornado.web.StaticFileHandler,
            {
                "path": path,
                "default_filename": "index.html"
            }
        ))

    def addUI(self, name, Handler):
        self.ui_modules[name] = Handler

    def template(self, path="templates"):
        self.template_path = FPLib.FILE(path)

    def bind(self, port):
        self.port = port

    def start(self, port=0):

        if port > 0:
            self.bind(port)
        settings = {
            "handlers": self.Handler + self.staticHandler,
            "autoreload": True,
            "ui_modules": self.ui_modules,
            "template_path": self.template_path,
            "debug": FPLib.conf.isdebug,
            "xheaders": True,
            "session": {
                "driver": "file",
                "driver_settings": {
                    "host": "#_sessions",
                },
                "sid_name": "FPLibSessionID",
                "session_lifetime": 1800,
                "force_persistence": True
            }

        }
        # if self.template_path != "":
        #     settings["template_path"]=self.template_path

        if self.is_single:
            self.app = tornado.web.Application(**settings)
            self.app.listen(self.port)

        else:
            settings["autoreload"] = False
            self.app = tornado.web.Application(**settings)

            self.server = tornado.httpserver.HTTPServer(self.app)
            self.server.bind(self.port)
            self.server.start(0)
        tornado.ioloop.IOLoop.current().start()
